import {
  Component,
  EventEmitter,
  Input,
  OnInit,
  Output,
  HostListener,
  ElementRef,
  forwardRef,
  HostBinding, ContentChildren, QueryList, AfterContentChecked
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { AppOptionComponent } from '../appOption/appOption';

@Component({
  selector: 'app-select',
  templateUrl: './appSelect.html',
  styleUrls: ['./appSelect.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: AppSelectComponent,
      multi: true
    }
  ]
})
export class AppSelectComponent implements OnInit, ControlValueAccessor, AfterContentChecked {

  @Input()
  placeholder: string;
  @Input()
  multiple: boolean;  // TODO
  @Input()
  disabled: boolean;
  @Output()
  change = new EventEmitter<any>();

  isShowOption: boolean;
  value: any;
  display: string;
  onChange: Function;

  @ContentChildren(AppOptionComponent)
  optionChildren: QueryList<AppOptionComponent>;

  ngAfterContentChecked() {
    // 为了异步数据设置值
    this.writeValue(this.value);

    this.optionChildren.forEach(oc => {
      if (oc.selectOption.observers.length === 0) {
        oc.selectOption.subscribe((val: any) => {
          this.onHideOption();
          if (val !== this.value) {
            this.writeValue(val);
            this.onChange(val);
            this.change.emit(val);
          }
        })
      }
    });
  }


  @HostListener('window:click', ['$event.target'])
  onWindowClick(target) {
    if (!this.elementRef.nativeElement.contains(target.parentNode)) {
      this.onHideOption();
    }
  }

  @HostBinding('style.opacity')
  get opacity() {
    return this.disabled ? 0.5 : 1;
  }

  constructor(private elementRef: ElementRef) {
  }

  ngOnInit() {

  }

  onShowOption() {
    if (this.disabled) {
      return false;
    }
    this.optionChildren.forEach(oc => {
      oc.selected = oc.value == this.value;
    });
    this.isShowOption = true;
  }

  onHideOption() {
    this.isShowOption = false;
  }

  getOptionDisplay(val: any): string {
    if (this.optionChildren) {
      // 服务器返回的val是字符串所以用==
      const oc = this.optionChildren.find(oc => oc.value == val);
      return oc ? oc.getDisplay() : this.placeholder;
    }
    return this.placeholder;
  }

  // Allows Angular to update the model.
  // Update the model and changes needed for the view here.
  // 将值写到组件
  writeValue(val: any): void {
    if (val !== undefined) {
      this.value = val;
      this.display = this.getOptionDisplay(val);
    } else {
      this.value = val;
      this.display = this.placeholder;
    }
  }

  // Allows Angular to register a function to call when the model changes.
  // Save the function as a property to call later here.
  // 组件值变化时调用onChange
  registerOnChange(fn: (val: any) => void): void {
    this.onChange = fn;
  }

  // Allows Angular to register a function to call when the input has been touched.
  // Save the function as a property to call later here.
  registerOnTouched(fn: () => void): void {
    // 不关心
  }

  // Allows Angular to disable the input.
  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }


}
